package com.bfl.sa.common.web.controller;

import com.bfl.sa.common.Constants;
import com.bfl.sa.common.entity.AbstractEntity;
import com.bfl.sa.common.entity.search.Searchable;
import com.bfl.sa.common.exception.AjaxException;
import com.bfl.sa.common.mybatis.entity.Query;
import com.bfl.sa.common.service.BaseService;
import com.bfl.sa.common.web.bind.annotation.PageableDefaults;
import com.bfl.sa.common.web.controller.permission.PermissionList;
import com.bfl.sa.common.web.validate.AjaxResponse;
import com.bfl.sa.common.web.validate.ValidateResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ui.Model;
import org.springframework.util.StringUtils;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import javax.validation.Valid;
import java.io.Serializable;

/**
 * 基础CRUD 控制器
 */
public abstract class BaseCRUDController<E extends AbstractEntity, K extends Serializable>
        extends BaseController<E> {

    protected BaseService<E, K> baseService;

    private boolean listAlsoSetCommonData = false;

    protected PermissionList permissionList = null;

    @Autowired
    public void setBaseService(BaseService<E, K> baseService) {
        this.baseService = baseService;
    }

    /**
     * 列表也设置common data
     */
    protected void setListAlsoSetCommonData(boolean listAlsoSetCommonData) {
        this.listAlsoSetCommonData = listAlsoSetCommonData;
    }

    /**
     * 权限前缀：如sys:user
     * 则生成的新增权限为 sys:user:create
     */
    public void setResourceIdentity(String resourceIdentity) {
        if (!StringUtils.isEmpty(resourceIdentity)) {
            permissionList = PermissionList.newPermissionList(resourceIdentity);
        }
    }

    /**
     * 页面 - 默认（列表）
     */
    @RequestMapping(method = RequestMethod.GET) @PageableDefaults(sort = "id=desc")
    public String list(Searchable searchable, Model model) {

        if (permissionList != null) {
            this.permissionList.assertHasViewPermission();
        }

        model.addAttribute("page", baseService.findPage(searchable));
        if (listAlsoSetCommonData) {
            setCommonData(model);
        }

        return viewName("list");
    }

    /**
     * 页面 - 默认（表格列表）
     */
    @RequestMapping(method = RequestMethod.GET, headers = "table=true") @PageableDefaults(sort = "id=desc")
    public String listTable(Searchable searchable, Model model) {
        list(searchable, model);
        return viewName("listTable");
    }

    /**
     * 请求 - 列表
     */
    @RequestMapping(value = "/list", method = RequestMethod.GET, produces = "application/json") @PageableDefaults(sort = "id=desc")
    @ResponseBody
    public AjaxResponse ajaxList(Searchable searchable) {
        return AjaxResponse.ok(baseService.findPage(searchable));
    }

    /**
     * 页面 - 查看
     */
    @RequestMapping(value = "/{id}", method = RequestMethod.GET)
    public String view(Model model, @PathVariable("id") E m) {

        if (permissionList != null) {
            this.permissionList.assertHasViewPermission();
        }

        setCommonData(model);
        model.addAttribute("m", m);
        model.addAttribute(Constants.OP_NAME, "查看");
        return viewName("editForm");
    }

    /**
     * 页面 - 新增
     */
    @RequestMapping(value = "create", method = RequestMethod.GET)
    public String showCreateForm(Model model) {

        if (permissionList != null) {
            this.permissionList.assertHasCreatePermission();
        }

        setCommonData(model);
        model.addAttribute(Constants.OP_NAME, "新增");
        if (!model.containsAttribute("m")) {
            model.addAttribute("m", newModel());
        }
        return viewName("editForm");
    }

    /**
     * 请求 - 新增
     */
    @RequestMapping(value = "create", method = RequestMethod.POST)
    public String create(Model model, @Valid @ModelAttribute("m") E m, BindingResult result, RedirectAttributes redirectAttributes) {

        if (permissionList != null) {
            this.permissionList.assertHasCreatePermission();
        }

        if (hasError(m, result)) {
            return showCreateForm(model);
        }
        baseService.save(m);
        redirectAttributes.addFlashAttribute(Constants.MESSAGE, "新增成功");
        return redirectToUrl(null);
    }

    /**
     * AJAX - 新增
     */
    @RequestMapping(value = "ajaxCreate", method = RequestMethod.POST)
    @ResponseBody
    public AjaxResponse ajaxCreate(@Valid @ModelAttribute("m") E m, BindingResult result) throws AjaxException {

        if (permissionList != null) {
            this.permissionList.assertHasCreatePermission();
        }

        if (hasError(m, result)) {
            return AjaxResponse.fail(getValidErrors(result));
        }

        baseService.save(m);
        return AjaxResponse.ok("新增成功");
    }

    /**
     * 页面 - 编辑
     */
    @RequestMapping(value = "{id}/update", method = RequestMethod.GET)
    public String showUpdateForm(@PathVariable("id") E m, Model model) {

        if (permissionList != null) {
            this.permissionList.assertHasUpdatePermission();
        }

        setCommonData(model);
        model.addAttribute(Constants.OP_NAME, "修改");
        model.addAttribute("m", m);
        return viewName("editForm");
    }

    /**
     * 请求 - 编辑
     */
    @RequestMapping(value = "{id}/update", method = RequestMethod.POST)
    public String update(Model model, @Valid @ModelAttribute("m") E m, BindingResult result, @RequestParam(value = Constants.BACK_URL, required = false) String backURL, RedirectAttributes redirectAttributes) {

        if (permissionList != null) {
            this.permissionList.assertHasUpdatePermission();
        }

        if (hasError(m, result)) {
            return showUpdateForm(m, model);
        }
        baseService.save(m);
        redirectAttributes.addFlashAttribute(Constants.MESSAGE, "修改成功");
        return redirectToUrl(backURL);
    }

    /**
     * 页面 - 删除
     */
    @RequestMapping(value = "{id}/delete", method = RequestMethod.GET)
    public String showDeleteForm(@PathVariable("id") E m, Model model) {

        if (permissionList != null) {
            this.permissionList.assertHasDeletePermission();
        }

        setCommonData(model);
        model.addAttribute(Constants.OP_NAME, "删除");
        model.addAttribute("m", m);
        return viewName("editForm");
    }

    /**
     * 请求 - 删除
     */
    @RequestMapping(value = "{id}/delete", method = RequestMethod.POST)
    @ResponseBody
    public AjaxResponse delete(@PathVariable("id") E m) {

        if (permissionList != null) {
            this.permissionList.assertHasDeletePermission();
        }

        baseService.delete(m);
        return AjaxResponse.ok();
    }

    /**
     * 请求 - 批量删除
     */
    @RequestMapping(value = "batch/delete", method = {RequestMethod.GET, RequestMethod.POST})
    public String deleteInBatch(@RequestParam(value = "ids", required = false) K[] ids, @RequestParam(value = Constants.BACK_URL, required = false) String backURL, RedirectAttributes redirectAttributes) {

        if (permissionList != null) {
            this.permissionList.assertHasDeletePermission();
        }

        baseService.delete(ids);

        redirectAttributes.addFlashAttribute(Constants.MESSAGE, "删除成功");
        return redirectToUrl(backURL);
    }

    @RequestMapping(value = "validate", method = RequestMethod.GET)
    @ResponseBody
    public Object validate(@RequestParam("fieldId") String fieldId, @RequestParam("fieldValue") String fieldValue, @RequestParam(value = "id", required = false) Long id) {

        ValidateResponse response = ValidateResponse.newInstance();

        Query query = Query.newQuery();
        query.put(fieldId, fieldValue);
        query.put("id", id);

        int count = baseService.count(query);
        if (count == 0) {
            response.validateSuccess(fieldId, "");
        } else {
            response.validateFail(fieldId, "已存在相同数据！");
        }

        return response.result();
    }

}
